package com.shine.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shine.context.SecurityContextHolder;
import com.shine.entity.Menu;
import com.shine.enums.MenuTypeEnum;
import com.shine.exception.BaseException;
import com.shine.info.MenuInfo;
import com.shine.mapper.MenuMapper;
import com.shine.request.MenuCreateRequest;
import com.shine.request.MenuPageRequest;
import com.shine.request.MenuUpdateRequest;
import com.shine.response.MenuResponse;
import com.shine.service.MenuService;
import com.shine.status.ResponseStatus;
import com.shine.utils.PageUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 菜单 服务实现类
 * </p>
 *
 * @author huihui
 * @since 2024-11-18
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Override
    public List<MenuResponse> listMenu(MenuPageRequest request) {
        List<Menu> menuList = this.baseMapper.selectList(
                Wrappers.<Menu>lambdaQuery()
                        .eq(StringUtils.isNotBlank(request.getName()), Menu::getName, request.getName())
        );
        if (CollectionUtils.isEmpty(menuList)) {
            return Collections.emptyList();
        }
        // 超级拼装
        List<Menu> parentList = menuList.stream().filter(item -> MenuTypeEnum.T0.getCode().equals(item.getType()) && item.getParentId().equals(0L)).toList();
        if (CollectionUtils.isEmpty(parentList)) {
            return Collections.emptyList();
        }
        return parentList.stream().map(item -> {
            MenuResponse menuInfo = new MenuResponse();
            BeanUtil.copyProperties(item, menuInfo, true);
            // 找儿子
            List<Menu> childrenList = menuList.stream().filter(children -> children.getParentId().equals(item.getId())).toList();
            // 儿子找孙子
            List<MenuResponse> childrenInfoList = childrenList.stream().map(children -> {
                MenuResponse childrenMenuInfo = new MenuResponse();
                BeanUtil.copyProperties(children, childrenMenuInfo, true);
                List<Menu> grandsonList = menuList.stream().filter(grandson -> grandson.getParentId().equals(children.getId())).toList();
                List<MenuResponse> grandsonInfoList = grandsonList.stream().map(build -> {
                    MenuResponse buildMenuInfo = new MenuResponse();
                    BeanUtil.copyProperties(build, buildMenuInfo, true);
                    return buildMenuInfo;
                }).toList();
                childrenMenuInfo.setChildren(grandsonInfoList);
                return childrenMenuInfo;
            }).toList();
            menuInfo.setChildren(childrenInfoList);
            return menuInfo;
        }).toList();
    }

    @Override
    public List<MenuInfo> getPermissionByUserId(Long userId) {
        if (userId == null) {
            log.error("获取用户权限无用户ID");
            return Collections.emptyList();
        }
        return this.baseMapper.listByUserId(1, userId);
    }

    @Override
    public List<MenuResponse> listByUserId(Long userId) {
        if (userId == null) {
            log.error("获取用户菜单无用户ID");
            return Collections.emptyList();
        }
        List<MenuResponse> responseList = new ArrayList<>();
        List<MenuInfo> menuInfoList = this.baseMapper.listByUserId(0, userId);
        List<MenuInfo> parentList = menuInfoList.stream().filter(item -> item.getParentId().equals(0L)).toList();
        if (CollectionUtils.isEmpty(parentList)) {
            return Collections.emptyList();
        }
        parentList.forEach(item -> {
            MenuResponse response = new MenuResponse();
            BeanUtil.copyProperties(item, response, true);
            List<MenuResponse> childrenList = menuInfoList.stream().filter(x -> x.getParentId().equals(item.getId()))
                    .map(x -> {
                        MenuResponse childrenResponse = new MenuResponse();
                        BeanUtil.copyProperties(x, childrenResponse, true);
                        return childrenResponse;
                    }).toList();
            response.setChildren(childrenList);
            responseList.add(response);
        });
        return responseList;
    }

    @Override
    public Boolean deleteById(Long id) {
        if (id == null) {
            throw new BaseException(ResponseStatus.PARAMS_ERROR_MISS_REMOVE_ID);
        }
        return removeById(id);
    }

    @Override
    public Boolean updateMenu(MenuUpdateRequest request) {
        if (request.getId() == null) {
            throw new BaseException(ResponseStatus.PARAMS_ERROR_MISS_UPDATE_ID);
        }
        Long userId = SecurityContextHolder.getContext().getPrincipal().getId();
        LambdaUpdateWrapper<Menu> wrapper = Wrappers.<Menu>lambdaUpdate()
                .eq(Menu::getId, request.getId())
                .set(Menu::getParentId, request.getParentId())
                .set(Menu::getName, request.getName())
                .set(Menu::getSort, request.getSort())
                .set(Menu::getPath, request.getPath())
                .set(Menu::getType, request.getType())
                .set(Menu::getPermission, request.getPermission())
                .set(Menu::getUpdateUser, userId);
        return this.update(wrapper);
    }

    @Override
    public Boolean saveMenu(MenuCreateRequest request) {
        Menu menu = new Menu();
        menu.setParentId(request.getParentId());
        menu.setName(request.getName());
        menu.setPath(request.getPath());
        menu.setPermission(request.getPermission());
        menu.setType(request.getType());
        menu.setIcon(request.getIcon());
        menu.setSort(request.getSort());
        menu.setStatus(request.getStatus());
        return this.save(menu);
    }
}
